package com.tyk.bookstore.back.logistics.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tyk.bookstore.back.common.core.model.type.BinVo;
import com.tyk.bookstore.back.common.core.model.type.SuggestionQuery;
import com.tyk.bookstore.back.common.core.util.AssertUtil;
import com.tyk.bookstore.back.common.core.util.IdGenerator;
import com.tyk.bookstore.back.common.core.util.ObjUtil;
import com.tyk.bookstore.back.logistics.manager.excel.model.ExpressCompanyExcelVo;
import com.tyk.bookstore.back.logistics.model.entity.ExpressCompanyDo;
import com.tyk.bookstore.back.logistics.model.query.ExpressCompanyAddQuery;
import com.tyk.bookstore.back.logistics.model.query.ExpressCompanyPageQuery;
import com.tyk.bookstore.back.logistics.model.query.ExpressCompanyUpdateQuery;
import com.tyk.bookstore.back.logistics.model.result.ExpressCompanyResultEnum;
import com.tyk.bookstore.back.logistics.model.vo.ExpressCompanyPageVo;
import com.tyk.bookstore.back.logistics.model.vo.ExpressCompanyVo;
import com.tyk.bookstore.back.logistics.repository.ExpressCompanyRepository;
import com.tyk.bookstore.back.logistics.service.ExpressCompanyService;
import com.tyk.bookstore.back.logistics.util.MapStructLogistics;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.util.List;
import java.util.Set;

/**
 * @author tyk
 * @description 快递公司管理
 */
@Service
@RequiredArgsConstructor
public class ExpressCompanyServiceImp implements ExpressCompanyService {

    private final ExpressCompanyRepository expressCompanyRepository;
    private final MapStructLogistics mapStructLogistics;

    @Override
    public ExpressCompanyVo getById(Long id) {
        // 物流公司存在
        AssertUtil.isTrue(
                expressCompanyRepository.exist1Eq(
                        ExpressCompanyDo::getId, id, ExpressCompanyDo.class
                ),
                ExpressCompanyResultEnum.EXPRESS_COMPANY_NOT_FOUND
        );
        // 查询并返回
        return mapStructLogistics.toExpressCompanyVo(expressCompanyRepository.selectById(id));
    }

    @Override
    public ExpressCompanyPageVo getPage(ExpressCompanyPageQuery query) {

        // 分页条件
        Page<ExpressCompanyDo> page = new Page<>(query.getPage(), query.getLimit());

        // 查询条件
        LambdaQueryWrapper<ExpressCompanyDo> w = buildPageQueryWrapper(query);

        // 查询
        expressCompanyRepository.selectPage(page, w);

        // 转换并返回
        return mapStructLogistics.toExpressCompanyPageVo(page);
    }


    @Override
    public void add(ExpressCompanyAddQuery query) {
        // 物流公司不存在
        AssertUtil.isFalse(
                expressCompanyRepository.exist1Eq(
                        ExpressCompanyDo::getBriefName, query.getBriefName(), ExpressCompanyDo.class
                ),
                ExpressCompanyResultEnum.EXPRESS_COMPANY_ALREADY_EXISTS
        );
        // 添加
        ExpressCompanyDo ec = mapStructLogistics.toExpressCompanyDo(query);
        ec.setId(IdGenerator.id());
        expressCompanyRepository.insert(ec);
    }

    @Override
    public void updateById(ExpressCompanyUpdateQuery query) {

        AssertUtil.isTrue(
                expressCompanyRepository.exist1Eq(
                        ExpressCompanyDo::getId, query.getId(), ExpressCompanyDo.class
                ),
                ExpressCompanyResultEnum.EXPRESS_COMPANY_NOT_FOUND
        );

        AssertUtil.isFalse(
                expressCompanyRepository.exist1Eq1Ne(
                        ExpressCompanyDo::getBriefName, query.getBriefName(),
                        ExpressCompanyDo::getId, query.getId(),
                        ExpressCompanyDo.class
                ),
                ExpressCompanyResultEnum.EXPRESS_COMPANY_ALREADY_EXISTS
        );

        ExpressCompanyDo expressCompany = mapStructLogistics.toExpressCompanyDo(query);
        expressCompanyRepository.updateById(expressCompany);
    }

    @Override
    public void deleteById(Long id) {

        AssertUtil.isTrue(
                expressCompanyRepository.exist1Eq(
                        ExpressCompanyDo::getId, id, ExpressCompanyDo.class
                ),
                ExpressCompanyResultEnum.EXPRESS_COMPANY_NOT_FOUND
        );

        expressCompanyRepository.deleteById(id);
    }

    @Override
    public void deleteBatchByIdSet(Set<Long> idSet) {

        AssertUtil.equal(
                expressCompanyRepository.count1In(
                        ExpressCompanyDo::getId, idSet, ExpressCompanyDo.class
                ),
                (long) idSet.size(),
                ExpressCompanyResultEnum.EXPRESS_COMPANY_NOT_FOUND
        );

        expressCompanyRepository.deleteBatchIds(idSet);
    }

    @Override
    public List<BinVo> getSuggestionList(SuggestionQuery query) {
        return expressCompanyRepository.<BigInteger, String>selectBinList1Like(
                ExpressCompanyDo::getId, ExpressCompanyDo::getBriefName,
                ExpressCompanyDo::getBriefName, query.getKeyword(),
                ExpressCompanyDo.class
        ).stream().map(it -> new BinVo(it.getV1().longValue(), it.getV2())).toList();
    }

    @Override
    public List<ExpressCompanyExcelVo> getExpressCompanyExcelVoList(ExpressCompanyPageQuery query) {
        LambdaQueryWrapper<ExpressCompanyDo> w = buildPageQueryWrapper(query);
        List<ExpressCompanyDo> doList = expressCompanyRepository.selectList(w);
        return mapStructLogistics.toExpressCompanyExcelVoList(doList);
    }

    @Override
    public void saveExpressCompanyExcelVoList(List<ExpressCompanyExcelVo> expressCompanyList) {
        List<ExpressCompanyDo> doList = mapStructLogistics.toExpressCompanyDoList(expressCompanyList);
        doList.forEach(it->it.setId(IdGenerator.id()));
        expressCompanyRepository.insertBatch(doList);
    }


    /**
     * 构建物流公司分页查询Wrapper
     */
    private LambdaQueryWrapper<ExpressCompanyDo> buildPageQueryWrapper(ExpressCompanyPageQuery query) {
        LambdaQueryWrapper<ExpressCompanyDo> w = new LambdaQueryWrapper<>();

        w.ge(query.getChargeFrom() != null, ExpressCompanyDo::getCharge, query.getChargeFrom());
        w.le(query.getChargeTo() != null, ExpressCompanyDo::getCharge, query.getChargeTo());

        w.ge(query.getCreateTimeFrom() != null, ExpressCompanyDo::getCreateTime, query.getCreateTimeFrom());
        w.le(query.getCreateTimeTo() != null, ExpressCompanyDo::getCreateTime, query.getCreateTimeTo());

        w.like(ObjUtil.notBlank(query.getFullName()), ExpressCompanyDo::getFullName, query.getFullName());

        w.orderByDesc(ExpressCompanyDo::getCreateTime);

        return w;
    }
}
